home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 February: Tool Chest / Dev.CD Feb 00 TC.toast / pc / what's new? / sample code / human interface toolbox / packagetool / utilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-02  |  11.4 KB  |  350 lines

  1. /*
  2.     file Utilities.c
  3.     
  4.     Description:
  5.     This file contains the a number of utility routines used in the
  6.     PackagTool example.  they have been moved to this file
  7.     to simplify the example.
  8.     
  9.     PackageTool is an application illustrating how to create application
  10.     packages in Mac OS 9.  It provides a simple interface for converting
  11.     correctly formatted folders into packages and vice versa.
  12.  
  13.     Copyright: © 1999 by Apple Computer, Inc.
  14.     all rights reserved.
  15.     
  16.     Disclaimer:
  17.     You may incorporate this sample code into your applications without
  18.     restriction, though the sample code has been provided "AS IS" and the
  19.     responsibility for its operation is 100% yours.  However, what you are
  20.     not permitted to do is to redistribute the source as "DSC Sample Code"
  21.     after having made changes. If you're going to re-distribute the source,
  22.     we require that you make it clear in the source that the code was
  23.     descended from Apple Sample Code, but that you've made changes.
  24.     
  25.     Change History (most recent first):
  26.     10/19/99 created
  27. */
  28.  
  29. #include "Utilities.h"
  30. #include <QuickDraw.h>
  31. #include <Gestalt.h>
  32. #include <Palettes.h>
  33. #include <Threads.h>
  34. #include <fp.h>
  35. #include <FinderRegistry.h>
  36. #include <Resources.h>
  37. #include <Processes.h>
  38.  
  39. /* ValidFSSpec verifies that *spec refers is formatted correctly, and it
  40.     verifies that it refers to an existing file in an existing directory on
  41.     and existing volume. If *spec is valid, the function returns noErr,
  42.     otherwise an error is returned. */
  43. OSErr ValidFSSpec(FSSpec *spec) {
  44.     FInfo fndrInfo;
  45.         /* check the name's size */
  46.     if (spec->name[0] + (sizeof(FSSpec) - sizeof(spec->name)) > sizeof(FSSpec)) return paramErr;
  47.         /* ckeck if it refers to a file */
  48.     return FSpGetFInfo(spec, &fndrInfo);
  49. }
  50.  
  51.  
  52. /* ResolveAliasQuietly resolves an alias using a fast search with no user interaction.  Our main loop
  53.     periodically resolves gFileAlias comparing the result to gTargetFile to keep the display up to date.
  54.     As a result, we would like the resolve alias call to be as quick as possible AND since the application
  55.     may be in the background when  it is called, we don't want any user interaction. */
  56. OSErr ResolveAliasQuietly(ConstFSSpecPtr fromFile, AliasHandle alias, FSSpec *target, Boolean *wasChanged) {
  57.     short aliasCount;
  58.     Boolean needsUpdate;
  59.     OSErr err;
  60.         /* set up locals */
  61.     aliasCount = 1;
  62.     needsUpdate = false;
  63.     *wasChanged = false;
  64.         /* call MatchAlias to resolve the alias.  
  65.             kARMNoUI = no user interaction,
  66.             kARMSearch = do a fast search. */
  67.     err = MatchAlias(NULL, (kARMNoUI | kARMSearch), alias, &aliasCount, target, &needsUpdate, NULL, NULL);
  68.     if (err == noErr) {
  69.             /* if the alias was changed, update it. */
  70.         err = UpdateAlias(fromFile, target, alias, wasChanged);
  71.     }
  72.     return err;
  73. }
  74.  
  75.  
  76.  
  77.  
  78. /* GrayOutBox grays out an area of the screen in the current grafport.  
  79.     *theBox is in local coordinates in the current grafport. This routine
  80.     is for direct screen drawing only.  */
  81. void GrayOutBox(Rect *theBox) {
  82.     long response;
  83.     Rect globalBox;
  84.     GDHandle maxDevice;
  85.     RGBColor rgbWhite = {0xFFFF, 0xFFFF, 0xFFFF}, rgbBlack = {0, 0, 0}, sForground, sBackground;
  86.     PenState penSave;
  87.         /* save the current drawing state */
  88.     GetPenState(&penSave);
  89.         /* if no color quickdraw, fail...*/
  90.     if (Gestalt(gestaltQuickdrawVersion, &response) != noErr) response = 0;
  91.     if (response >= gestalt8BitQD) {
  92.             /* get the device for the rectangle */
  93.         globalBox = *theBox;
  94.         LocalToGlobal((Point*) &globalBox.top);
  95.         LocalToGlobal((Point*) &globalBox.bottom);
  96.         maxDevice = GetMaxDevice(&globalBox);
  97.         if (maxDevice != NULL) {
  98.                 /* calculate the best gray */
  99.             if ( GetGray(maxDevice, &rgbWhite, &rgbBlack)) {
  100.                     /* draw over the area in gray using addMax transfer mode */
  101.                 GetForeColor(&sForground);
  102.                 GetBackColor(&sBackground);
  103.                 RGBForeColor(&rgbBlack);
  104.                 RGBBackColor(&rgbWhite);
  105.                 PenMode(addMax);
  106.                 PaintRect(theBox);
  107.                 RGBForeColor(&sForground);
  108.                 RGBBackColor(&sBackground);
  109.                     /* restore the pen state and leave */
  110.                 SetPenState(&penSave);
  111.                 return;
  112.             }
  113.         }
  114.     }
  115.         /* fall through to using the gray pattern */
  116.     {    Pattern ggray;
  117.         GetQDGlobalsGray(&ggray);
  118.         PenPat(&ggray);
  119.         PenMode(notPatBic);
  120.         PaintRect(theBox);
  121.         SetPenState(&penSave);
  122.     }
  123. }
  124.  
  125.  
  126. /* ShowDragHiliteBox is called to hilite the drop box area in the
  127.     main window.  Here, we draw a 3 pixel wide border around *boxBounds.  */
  128. OSErr ShowDragHiliteBox(DragReference theDragRef, Rect *boxBounds) {
  129.     RgnHandle boxRegion, insetRegion;
  130.     OSErr err;
  131.     Rect box;
  132.         /* set up locals */
  133.     boxRegion = insetRegion = NULL;
  134.         /* create the region */
  135.     if ((boxRegion = NewRgn()) == NULL) { err = memFullErr; goto bail; }
  136.     if ((insetRegion = NewRgn()) == NULL) { err = memFullErr; goto bail; }
  137.     box = *boxBounds;
  138.     InsetRect(&box, -5, -5);
  139.     RectRgn(boxRegion, &box);
  140.     InsetRect(&box, 3, 3);
  141.     RectRgn(insetRegion, &box);
  142.     DiffRgn(boxRegion, insetRegion, boxRegion);
  143.         /* hilite the region */
  144.     err = ShowDragHilite(theDragRef, boxRegion, true);
  145. bail:
  146.         /* clean up and leave */
  147.     if (boxRegion != NULL) DisposeRgn(boxRegion);
  148.     if (insetRegion != NULL) DisposeRgn(insetRegion);
  149.     return err;
  150. }
  151.  
  152.  
  153.  
  154. /* UpdateRelativeAliasFile updates the alias file located at
  155.      aliasDest referring to the targetFile.  relative path
  156.      information is stored in the new file. */
  157. OSErr UpdateRelativeAliasFile(FSSpec *theAliasFile, FSSpec *targetFile, Boolean createIfNecessary) {
  158.     FInfo fndrInfo;
  159.     AliasHandle theAlias;
  160.     Boolean wasChanged;
  161.     short rsrc;
  162.     OSErr err;
  163.          /* set up locals */
  164.     rsrc = -1;
  165.          /* set up our the alias' file information */
  166.     err = FSpGetFInfo(targetFile, &fndrInfo);
  167.     if (err != noErr) goto bail;
  168.     if (fndrInfo.fdType == 'APPL')
  169.     fndrInfo.fdType = kApplicationAliasType;
  170.     fndrInfo.fdFlags = kIsAlias;
  171.          /* set the file information or the new file */
  172.     err = FSpSetFInfo(theAliasFile, &fndrInfo);
  173.     if ((err == fnfErr) && createIfNecessary) {
  174.         FSpCreateResFile( theAliasFile, fndrInfo.fdCreator, fndrInfo.fdType, smSystemScript);
  175.         if ((err = ResError()) != noErr) goto bail;
  176.         err = FSpSetFInfo( theAliasFile, &fndrInfo);
  177.         if (err != noErr) goto bail;
  178.     } else if (err != noErr) goto bail;
  179.          /* save the resource */
  180.     rsrc = FSpOpenResFile(theAliasFile, fsRdWrPerm);
  181.     if (rsrc == -1) { err = ResError(); goto bail; }
  182.     UseResFile(rsrc);
  183.     theAlias = (AliasHandle) Get1IndResource(rAliasType, 1);
  184.     if (theAlias != NULL) {
  185.         err = UpdateAlias(theAliasFile, targetFile, theAlias, &wasChanged);
  186.         if (err != noErr) goto bail;
  187.         if (wasChanged)
  188.             ChangedResource((Handle) theAlias);
  189.     } else {
  190.         err = NewAlias(theAliasFile, targetFile, &theAlias);
  191.         if (err != noErr) goto bail;
  192.         AddResource((Handle) theAlias, rAliasType, 0, theAliasFile->name);
  193.         if ((err = ResError()) != noErr) goto bail;
  194.     }
  195.     CloseResFile(rsrc);
  196.     rsrc = -1;
  197.         /* done */
  198.     return noErr;
  199.  bail:
  200.     if (rsrc != -1) CloseResFile(rsrc);
  201.     return err;
  202.  }
  203.  
  204.  
  205. enum {
  206.     kFileSharingSignature = 'hhgg' /* Macintosh File Sharing */
  207. };
  208.  
  209. /* FileSharingAppIsRunning returns true if the file sharing
  210.     extension is running. */
  211. Boolean FileSharingAppIsRunning(void) {
  212.     ProcessSerialNumber psn;
  213.     ProcessInfoRec pinfo;
  214.  
  215.     psn.highLongOfPSN = psn.lowLongOfPSN = kNoProcess;
  216.     pinfo.processInfoLength = sizeof(ProcessInfoRec);
  217.     pinfo.processName = NULL;
  218.     pinfo.processAppSpec = NULL;
  219.     while (GetNextProcess(&psn) == noErr)
  220.         if (GetProcessInformation(&psn, &pinfo) == noErr)
  221.             if (pinfo.processSignature == kFileSharingSignature)
  222.                 return true;
  223.     return false;
  224. }
  225.  
  226.  
  227. /* FSSpecIsInDirectory returns true if the file system object
  228.     referred to by theSpec is somewhere in the directory referred
  229.     to by (vRefNum, dirID) */
  230. Boolean FSSpecIsInDirectory(FSSpec *theSpec, short vRefNum, long dirID) {
  231.     CInfoPBRec cat;
  232.     HParamBlockRec fvol, dirvol;
  233.     long currentDir;
  234.         /* check the volumes */
  235.     fvol.volumeParam.ioVRefNum = theSpec->vRefNum;
  236.     fvol.volumeParam.ioNamePtr = NULL;
  237.     fvol.volumeParam.ioVolIndex = 0;
  238.     if (PBHGetVInfoSync(&fvol)) return false;
  239.     dirvol.volumeParam.ioVRefNum = vRefNum;
  240.     dirvol.volumeParam.ioNamePtr = NULL;
  241.     dirvol.volumeParam.ioVolIndex = 0;
  242.     if (PBHGetVInfoSync(&dirvol) != noErr) return false;
  243.     if (fvol.volumeParam.ioVRefNum != dirvol.volumeParam.ioVRefNum) return false;
  244.         /* check if the directory is one of the file's parents */
  245.     currentDir = theSpec->parID;
  246.     while (true) {
  247.         if (dirID == currentDir) return true;
  248.         if (currentDir == 2) return false;
  249.             /* make sure it refers to a file in the package's directory */
  250.         BlockZero(&cat, sizeof(cat));
  251.         cat.dirInfo.ioNamePtr = NULL;
  252.         cat.dirInfo.ioVRefNum = theSpec->vRefNum;
  253.         cat.dirInfo.ioFDirIndex = -1;
  254.         cat.dirInfo.ioDrDirID = currentDir;
  255.         if (PBGetCatInfoSync(&cat) != noErr) return false;
  256.         currentDir = cat.dirInfo.ioDrParID;
  257.     }
  258. }
  259.  
  260.  
  261. /* FSSpecIsAFolder returns true if the FSSpec pointed
  262.     to by target refers to a folder. */
  263. Boolean FSSpecIsAFolder(FSSpec *target) {
  264.     CInfoPBRec cat;
  265.     OSErr err;
  266.         /* check the target's flags */
  267.     cat.dirInfo.ioNamePtr = target->name;
  268.     cat.dirInfo.ioVRefNum = target->vRefNum;
  269.     cat.dirInfo.ioFDirIndex = 0;
  270.     cat.dirInfo.ioDrDirID = target->parID;
  271.     err = PBGetCatInfoSync(&cat);
  272.     if (err != noErr) return false;
  273.     return ((cat.dirInfo.ioFlAttrib & 16) != 0);
  274. }
  275.  
  276.  
  277. /* ShowChangesInFinderWindow asks the finder redraw a directory
  278.     window by either sending a update container event to the
  279.     finder if this facility exists, or by bumping the parent directorie's
  280.     modification date */
  281. OSErr ShowChangesInFinderWindow(short vRefNum, long dirID) {
  282.     OSErr err;
  283.     long response;
  284.     CInfoPBRec cat;
  285.     Str255 name;
  286.         /* get information about the directory */
  287.     cat.hFileInfo.ioNamePtr = name;
  288.     cat.hFileInfo.ioVRefNum = vRefNum;
  289.     cat.hFileInfo.ioDirID = dirID;
  290.     cat.hFileInfo.ioFDirIndex = -1;
  291.     if ((err = PBGetCatInfoSync(&cat)) != noErr) return err;
  292.         /* determine what we can do... */
  293.     if (Gestalt(gestaltFinderAttr, &response) != noErr) response = 0;
  294.     if ((response & (1<<gestaltOSLCompliantFinder)) != 0) {
  295.         AppleEvent the_apple_event, the_reply;
  296.         AEAddressDesc target_desc;
  297.         FSSpec spec;
  298.         OSType app_creator;
  299.         long actualSize, the_error;
  300.         DescType actualType;
  301.     
  302.             /* set up a recoverable state */
  303.         AECreateDesc(typeNull, NULL, 0, &the_apple_event);
  304.         AECreateDesc(typeNull, NULL, 0, &target_desc);
  305.         AECreateDesc(typeNull, NULL, 0, &the_reply);
  306.  
  307.             /* create an update event targeted at the finder */
  308.         app_creator = 'MACS';
  309.         err = AECreateDesc(typeApplSignature, (Ptr) &app_creator,
  310.             sizeof(app_creator), &target_desc);
  311.         if (err != noErr) goto send_update_abort;
  312.         err = AECreateAppleEvent(kAEFinderSuite, kAEUpdate,
  313.             &target_desc, kAutoGenerateReturnID,
  314.             kAnyTransactionID, &the_apple_event);
  315.         if (err != noErr) goto send_update_abort;
  316.  
  317.             /* add the FSSpec parameter */
  318.         err = FSMakeFSSpec(vRefNum, cat.dirInfo.ioDrParID, name, &spec);
  319.         if (err != noErr) goto send_update_abort;
  320.         err = AEPutParamPtr(&the_apple_event, keyDirectObject, typeFSS, &spec, sizeof(FSSpec));
  321.         if (err != noErr) goto send_update_abort;
  322.  
  323.             /* send the apple event */
  324.         err = AESend(&the_apple_event, &the_reply, kAENoReply,
  325.             kAENormalPriority, kNoTimeOut, NULL, NULL);
  326.         
  327.         err = AEGetParamPtr(&the_reply, keyErrorNumber, typeLongInteger,
  328.             &actualType, &the_error, 4, &actualSize);
  329.         if (err == errAEDescNotFound)
  330.             err = noErr;
  331.         else if (err == noErr)
  332.             err = the_error;
  333.  
  334.     send_update_abort:
  335.         AEDisposeDesc(&the_apple_event);
  336.         AEDisposeDesc(&target_desc);
  337.         AEDisposeDesc(&the_reply);
  338.  
  339.     } else {    /* bump the date for the directory so the finder notices */
  340.         unsigned long secs;
  341.         GetDateTime(&secs);
  342.         cat.hFileInfo.ioFlMdDat = (secs == cat.hFileInfo.ioFlMdDat) ? (++secs) : (secs);
  343.         cat.hFileInfo.ioDirID = cat.dirInfo.ioDrParID;
  344.         err = PBSetCatInfoSync(&cat);
  345.     }
  346.     return err;
  347. }
  348.  
  349.  
  350.